package com.herui.ota.config;

import com.herui.ota.enums.ResponseEnum;
import com.herui.ota.exception.ServiceException;
import com.mlnx.common.entity.Response;
import org.apache.commons.lang3.StringUtils;
import org.shan.base.layer.user.pojo.dto.UserRightDto;
import org.shan.base.layer.user.service.UserAccountService;
import org.shan.security.core.authentication.userinfo.UserInfoProcess;
import org.shan.security.core.authorize.AuthorizeConfigProvider;
import org.shan.security.core.role.RbacService;
import org.shan.security.core.role.iml.RbacServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * Created by amanda.shan on 2019/7/1.
 */
@Configuration
@AutoConfigureOrder(1)
public class AuthConfig {

    @Autowired
    private UserAccountService userService;

    @Bean("rbacService")
    public RbacService rbacService() {
        return new RbacServiceImpl();
    }

    @Bean
    public MlnxWebResponseExceptionTranslator translator() {
        return new MlnxWebResponseExceptionTranslator();
    }

    // 解析接口请求异常的处理类 下面只处理登入异常的情况
    static class MlnxWebResponseExceptionTranslator extends DefaultWebResponseExceptionTranslator {

        @Override
        public ResponseEntity translate(Exception e) throws Exception {

            if (e instanceof ServiceException) {
                HttpHeaders headers = new HttpHeaders();
                ResponseEntity response = new ResponseEntity(new Response(ResponseEnum.LOGIN_FAIL.getCode(),
                        e.getMessage()), headers, HttpStatus.FORBIDDEN);

                return response;

            } else {
                return super.translate(e);
            }
        }

    }

//    @Bean
//    @ConditionalOnMissingBean({PasswordEncoder.class})
//    public PasswordEncoder passwordEncoder() {
//        return new PasswordEncoder() {
//            @Override
//            public String encode(CharSequence charSequence) {
//                return charSequence.toString();
//            }
//
//            @Override
//            public boolean matches(CharSequence charSequence, String s) {
//                return charSequence.toString().equals(s);
//            }
//        };
//    }

    @Bean
    @Primary
    public UserDetailsService userDetailsService(PasswordEncoder encoder) {
        return new UserDetailsService() {
            @Override
            public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

                UserRightDto userRoleDto = userService.getUserRoleDto(username);
                if (userRoleDto == null) {
                    userRoleDto = new UserRightDto();
                }

                // 加入权限
                String[] strings = new String[0];
                if (userRoleDto.getRightKeys() != null) {
                    strings = userRoleDto.getRightKeys().toArray(new String[0]);
                }

                String password = userRoleDto.getPassword();
                if (StringUtils.isEmpty(password)) {
                    password = "123456";
                }

                return new User(username, encoder.encode(password), AuthorityUtils.createAuthorityList(strings));
            }
        };
    }

    /**
     * 设置url拦截权限
     *
     * @return
     */
    @Bean
    public AuthorizeConfigProvider authorizeConfigProvider() {
        return new AuthorizeConfigProvider() {

            @Override
            public boolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
//                registry.anyRequest().permitAll();
                registry.antMatchers("/**")
                        .access("@rbacService.hasPermission(request,authentication)");
                registry.antMatchers(HttpMethod.POST, "/ota/**")
                        .access("@rbacService.hasPermission(request,authentication)");
                registry.antMatchers(HttpMethod.PUT, "/ota/**")
                        .access("@rbacService.hasPermission(request,authentication)");

//                registry.antMatchers("/ota_help/**")
//                        .access("@rbacService.hasPermission(request,authentication)");
                return true;
            }
        };
    }

    @Bean
    public UserInfoProcess userInfoProcess() {
        return new UserInfoProcess() {
            @Override
            public void process(Authentication authentication, HttpServletRequest httpServletRequest,
                                HttpServletResponse httpServletResponse) {

                String username = null;
                Object principal = authentication.getPrincipal();
                if (principal instanceof User) {
                    User user = (User) principal;
                    username = user.getUsername();
                } else {
                    username = principal.toString();
                }

                if (!StringUtils.isEmpty(username)) {
                    httpServletRequest.setAttribute("username", username);
                }
            }
        };
    }

}
